<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<title>litegl.js: instancing example</title>
	<link rel="stylesheet" type="text/css" href="style.css" />
	<style type='text/css'>
		html, body { width: 100%; height: 100%; margin: 0; padding: 0 }
		body { background-color: #DDD;}
		h1 { color: #777; background-color: #CCC; }
		button { position: fixed; top: 0; left: 0; z-index:1; padding:0.2em; font-size: 2em;}
	</style>

</head>
<body>
	<script type="text/javascript" src="../external/gl-matrix.js"></script>
	<script type="text/javascript" src="../build/litegl.js"></script>
	<script type="text/javascript">
	//create the rendering context
	var container = document.body;

	var gl = GL.create({ version:1, width: container.offsetWidth, height: container.offsetHeight});
	container.appendChild(gl.canvas);
	gl.animate(); //launch loop

	var mesh = GL.Mesh.cube();

	//build the mesh
	var objects = [];
	for(var i = 0; i < 256; i++)
		objects.push( mat4.create() );

	//create basic matrices for cameras and transformation
	var proj = mat4.create();
	var view = mat4.create();
	var model = mat4.create();
	var vp = mat4.create();
	var temp = mat4.create();

	//set the camera position
	mat4.perspective(proj, 45 * DEG2RAD, gl.canvas.width / gl.canvas.height, 0.1, 1000);
	mat4.lookAt( view, [0,20,20],[0,0,0], [0,1,0]);
	mat4.multiply(vp, proj, view);

	//basic phong shader
	var shader = new Shader('\
			precision highp float;\
			attribute vec3 a_vertex;\
			attribute vec3 a_normal;\
			varying vec3 v_normal;\
			attribute mat4 u_model;\
			uniform mat4 u_viewprojection;\
			void main() {\
				vec3 pos = (u_model * vec4(a_vertex,1.0)).xyz;\
				v_normal = (u_model * vec4(a_normal,0.0)).xyz;\
				gl_Position = u_viewprojection * vec4(pos,1.0);\
			}\
			', '\
			precision highp float;\
			varying vec3 v_normal;\
			uniform vec3 u_lightvector;\
			uniform vec4 u_color;\
			void main() {\
			  vec3 N = normalize(v_normal);\
			  gl_FragColor = u_color * max(0.0, dot(u_lightvector,N));\
			}\
		');


	//generic gl flags and settings
	gl.clearColor(0.1,0.1,0.1,1);
	gl.enable( gl.DEPTH_TEST );

	var uniforms = {
		u_color: [1,1,1,1],
		u_lightvector: vec3.normalize(vec3.create(),[1,1,0.5]),
		u_model: model,
		u_viewprojection: vp
	};

	var instancing_data = new Float32Array( 16 * 1024 );

	/*
	var uniformLocation = shader.attributes.u_model;
	var instancing_buffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, instancing_buffer);
	gl.bufferData(gl.ARRAY_BUFFER, instancing_data, gl.STREAM_DRAW);
	for(var k = 0; k < 4; ++k)
	{
		gl.enableVertexAttribArray( uniformLocation+k );
		gl.vertexAttribPointer( uniformLocation+k, 4, gl.FLOAT , false, 16*4, k*4*4 );
		ext.vertexAttribDivisorANGLE( uniformLocation+k, 1 ); // This makes it instanced!
	}
	if(indexBuffer)
		ext.drawElementsInstancedANGLE( primitive, length, indexBuffer.buffer.gl_type, 0, batch.length);
	else
		ext.drawArraysInstancedANGLE( primitive, 0, length, batch.length);
	*/


	//rendering loop
	gl.ondraw = function()
	{
		gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );

		shader.uniforms(uniforms);
		shader.drawInstanced( mesh, GL.TRIANGLES, "triangles", { u_model: objects } );

		//create modelview and projection matrices
		/*
		for(var i in objects)
		{
			var model = objects[i];
			shader.setUniform("u_model",model);
			shader.draw(mesh);
		}
		*/
	};

	//update loop
	gl.onupdate = function(dt)
	{
		var time = getTime() * 0.001;
		var offset = 2 * Math.PI;
		for( var i = 0; i < objects.length; ++i )
		{
			var matrix = objects[i];
			mat4.identity( matrix );
			var f = i / objects.length;
			mat4.translate( matrix, matrix, [ Math.sin( f * offset + time * 2 ) * 10, Math.sin( f * offset * 1.2 + time ) * 2, Math.cos( f * offset + time ) * 10 ] );
			var s = Math.sin( f + time * 2) * 0.5 + 1.1;
			mat4.scale( matrix, matrix, [ s, s, s] );
		}
	};

	</script>
</body>
</html>


